package com.attendcollatesys.service.impl;

import com.attendcollatesys.entity.ATLeaveExtraDetail;
import com.attendcollatesys.entity.page.PaginationHelper;
import com.attendcollatesys.entity.vo.ATLeaveExtraDetailVO;
import com.attendcollatesys.entity.vo.ATLeaveExtraVO;
import com.attendcollatesys.ex.handler.ex.MessageNullValueException;
import com.attendcollatesys.mapper.ATDayDetailMapper;
import com.attendcollatesys.mapper.ATLeaveExtraDetailMapper;
import com.attendcollatesys.service.ATLeaveExtraDetailService;
import com.attendcollatesys.service.AtteResultsService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class ATLeaveExtraDetailServiceImpl implements ATLeaveExtraDetailService {

    public static String qingJ = "请假";
    public static String[] dayType = {"半天","一天"};

    @Autowired
    private ATLeaveExtraDetailMapper atLeaveExtraDetailMapper;

    @Autowired
    private ATDayDetailMapper atDayDetailMapper;

    @Autowired
    private AtteResultsService atteResultsService;

    @Override
    public int insertBatch(List<ATLeaveExtraDetail> list) {
        return atLeaveExtraDetailMapper.insertBatch(list);
    }

    @Override
    public int deleteByRequestNo(List<String> list) {
      return atLeaveExtraDetailMapper.deleteByRequestNo(list);
    }

    /**
     *
     * @param params  Map<String,String> params
     *           currentMonth:2023-01-01;必填
     *                name:非必填
     *                rtxNumber：非必填
     * @return List<Map<String,String>>
     *     每个map
     *            "rtxNumber": "zkr_wangziyi", 唯一标识
     *            "time": "0.5",    请假天长
     *            "abName": "王梓屹",  名字
     *            "day": "2023-10-31" 哪一天的假
     * @throws MessageNullValueException
     */
    @Override
    public List<Map<String,String>> selectAbnormalAttendance(Map<String,String> params) throws MessageNullValueException {

        //获取向后传递的数据
        Map<String,String> tStartEndNameRtx = new HashMap();
        //need  "startDate","endDate","name","rtxNumber"
        String tCurrentMonth = params.get("currentMonth");
        //计算获取起始日期
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate startDate = LocalDate.parse(tCurrentMonth) ;
        LocalDate endDate = startDate.plusMonths(1).minusDays(1);
        DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        tStartEndNameRtx.put("startDate",formatter.format(startDate));
        tStartEndNameRtx.put("endDate",formatter.format(endDate));
        tStartEndNameRtx.put("name",params.get("name"));
        tStartEndNameRtx.put("rtxNumber",params.get("rtxNumber"));

        //获取原始数据
        List<ATLeaveExtraDetail> tYuanValue = atLeaveExtraDetailMapper.queryBetwStartEndNameRtx(tStartEndNameRtx);

        //判空验证
        if(tYuanValue == null || tYuanValue.isEmpty()){
            //此月份下无数据
            return null;
        }

        //组装返回数据
        SimpleDateFormat sim = new SimpleDateFormat("yyyy-MM-dd");//工具
        ATLeaveExtraDetailVO results = new ATLeaveExtraDetailVO();
        List<Map<String,String>> tReturn= new ArrayList<>();
        int total= 0;
        for (int i = 0; i < tYuanValue.size(); i++) {
            Map<String,String> result = new HashMap<>();
            /**
             * "day":"2023-01-10",
             * "time":"0.5",请假时间
             * "rtxNumber":"",
             * "abName":"ww",
             */
            LocalDate xhDay =null;
            if (tYuanValue.get(i).getStartDay().equals(tYuanValue.get(i).getDeadlineDay())) {
                //开始与截止天相同
                total++;

                xhDay = LocalDate.parse(sim.format(tYuanValue.get(i).getStartDay()));
                String tYPinJDay = xhDay.format(formatter);

                result.put("abName",tYuanValue.get(i).getName());
                result.put("rtxNumber",tYuanValue.get(i).getRtxNumber());
                if (tYuanValue.get(i).getLeaveStartType().equals(tYuanValue.get(i).getDeadlineType())){
                    result.put("day",tYPinJDay);
                    result.put("time","0.5");//半天
                }else {
                    result.put("day",tYPinJDay);
                    result.put("time","1");//一天
                }
                tReturn.add(result);
            }else{
                //开始与截止天不同
                xhDay = LocalDate.parse(sim.format(tYuanValue.get(i).getStartDay()));
                String tYPinJDay = xhDay.format(formatter);

                LocalDate dlDay = LocalDate.parse(sim.format(tYuanValue.get(i).getDeadlineDay()));
                if (xhDay.isAfter(dlDay)) {
                    throw new MessageNullValueException("原始数据中，"+tYuanValue.get(i).getRequestNumber()+"放假请求，起止日期错误！");
                }
                //计算第一天
                total++;
                result.put("abName",tYuanValue.get(i).getName());
                result.put("rtxNumber",tYuanValue.get(i).getRtxNumber());

                if (tYuanValue.get(i).getLeaveStartType().equals("上午")){
                    result.put("day",tYPinJDay);//1天
                    result.put("time","1");//1天
                }else{
                    result.put("day",tYPinJDay);//1天
                    result.put("time","0.5");//半天
                }
                tReturn.add(result);

                //计算其他的天
                while(!xhDay.isEqual(dlDay)){
                    result = new HashMap<>();
                    xhDay = xhDay.plusDays(1);//增加一天

                    tYPinJDay = xhDay.format(formatter);

                    total++;
                    result.put("abName",tYuanValue.get(i).getName());
                    result.put("rtxNumber",tYuanValue.get(i).getRtxNumber());

                    //计算最后一天
                    if (xhDay.isEqual(dlDay)){
                        if (tYuanValue.get(i).getDeadlineType().equals("上午")){
                            result.put("day",tYPinJDay);//0.5天
                            result.put("time","0.5");//半天
                        }else {
                            result.put("day",tYPinJDay);//1天
                            result.put("time","1");//半天
                        }
                        tReturn.add(result);
                        break;
                    }else{
                        result.put("day",tYPinJDay);//1天
                        result.put("time","1");//半天
                    }
                    tReturn.add(result);
                }
            }
        }//循环结束
        return tReturn;
    }



    @Override
    public ATLeaveExtraDetailVO selectAllAbnormal(Map<String, String> params) throws MessageNullValueException, ParseException {
        //时间转换公式定义
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        String tCurrentMonth = params.get("currentMonth");
        //计算获取起始日期
        String tName = params.get("name");
        String tRtxNumber = params.get("rtxNumber");

        //截取列表的数目
        Integer pageNum = 1;
        Integer pageSize = 1000;
        if(params.get("pageNum") == null || "".equals(params.get("pageNum"))){
            //使用默认值1
        }else{
            pageNum = Integer.valueOf(params.get("pageNum"));
        }

        if(params.get("pageSize") == null || "".equals(params.get("pageSize"))){
            //默认1000
        }else{
            pageSize = Integer.valueOf(params.get("pageSize"));
        }

        List<String> rtxList = atDayDetailMapper.selRtxByNameDateRtx(tCurrentMonth, tName, tRtxNumber);

        if (rtxList == null || rtxList.isEmpty()) {
            throw new MessageNullValueException("此月暂时无数据！");
        }

        String yearMonth = tCurrentMonth.substring(0, 7).replace("-", "");
        List<Map<String, String>> abnormalSheet = new ArrayList<>();

        //无对应的返回数据，则跳过本次循环
        for (int onrtx = 0 ; onrtx< rtxList.size();onrtx++) {//每次循环出一个人的数据
            String s = rtxList.get(onrtx);
            Map<String,String> tRtxAll = atteResultsService.buildDetailResult(yearMonth, s);
            //如果无返回数据集，则跳过本次循环
            if(tRtxAll == null || tRtxAll.isEmpty()){
                continue;
            }

            //对一个人一个月的每日数据进行循环。
            String name = tRtxAll.get("name");
            tRtxAll.remove("name");
            for (int i = 1; i <= 32; i++) {//每人每天的数据循环

                //非null，非“”，非“√”
                String date = ""+i;
                if (tRtxAll.get(date) != null&& !"".equals(tRtxAll.get(date)) && !"√".equals(tRtxAll.get(date))){

                    Map<String,String> tResult = new HashMap<>();//此处为一个返回值。
                    //前缀时间计算
                    StringBuffer dayTime1 = new StringBuffer(yearMonth);
                    if (i<10){
                        dayTime1.append("0").append(i);
                    }else {
                        dayTime1.append(i);
                    }
                    //获取带——的日期
                    String year = dayTime1.substring(0, 4);
                    String month = dayTime1.substring(4, 6);
                    String day = dayTime1.substring(6, 8);
                    // 使用StringBuilder来组合它们，并插入破折号
                    StringBuilder output = new StringBuilder();
                    output.append(year).append("-").append(month).append("-").append(day);

                    String gangTime = output.toString();


                    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
                    //用于查询数据库
                    SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
                    Date date1 = sdf.parse(dayTime1.toString());

                    Date date2 = sdf2.parse(gangTime);
                    //用于显示到前端
                    SimpleDateFormat outputFormat = new SimpleDateFormat("MM月dd日");
                    String formattedDate = outputFormat.format(date1);

                    tResult.put("grpGroup","团险系统");//写死
                    tResult.put("rtxNumber",s);
                    tResult.put("abName",name);
                    tResult.put("illustrate",formattedDate + tRtxAll.get(date));
                    //按日期与rtxNumber单独开一次查询
                    if (tRtxAll.get(date).contains("假")){
                        ATLeaveExtraDetail atLeaveExtraDetail = atLeaveExtraDetailMapper.selectByStartEndRtx(s,date2);
                        if (atLeaveExtraDetail == null){
                            //加班请假表中无记录的请假记录
                            tResult.put("head","");
                        }else{
                            tResult.put("head",atLeaveExtraDetail.getProjectManager() ==null || "".equals(atLeaveExtraDetail.getProjectManager())?"":atLeaveExtraDetail.getProjectManager());
                        }
                    }else {
                        //去除默认值刘
                        tResult.put("head","");
                    }
                    abnormalSheet.add(tResult);
                }
            }
        }

        ATLeaveExtraDetailVO results = new ATLeaveExtraDetailVO();
        PaginationHelper<Map<String,String>> thisPage = new PaginationHelper(abnormalSheet,pageSize, pageNum);
        results.setAbnormalSheet(thisPage.getPageData());
        results.setTotal(abnormalSheet.size());
        return results;
    }


    /**
     *
     * @param params
     * "startDate": "",
     *     "endDate":"",
     *     "name":"",
     *     "tayps":"",
     *     "rtxNumber":"",
     *         "pageNum": 1,
     *         "pageSize": 10
     * @return
     * @throws MessageNullValueException
     * @throws ParseException
     */
    @Override
    public Map<String, Object> selectAllByTaypsExServ(Map<String, Object> params) throws MessageNullValueException, ParseException {

        //时间转换公式定义
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        //获取起始日期
        String startDate = (String) params.get("startDate");
        String endDate = (String) params.get("endDate");
        if (startDate == null || "".equals(startDate)||endDate == null || "".equals(endDate)){
            throw new MessageNullValueException("起止日期传入错误！");
        }

        String tName = params.get("name")==null?"":(String) params.get("name");
        String tRtxNumber = params.get("rtxNumber")==null?"":(String) params.get("rtxNumber");
        String tayps = params.get("tayps")==null?"Q":(String) params.get("tayps");

        //截取列表的数目
        Integer pageNum = params.get("pageNum")==null?1:(Integer) params.get("pageNum");
        Integer pageSize = params.get("pageSize")==null?10:(Integer) params.get("pageSize");
        //pageHelper的准备
        PageHelper.startPage(pageNum, pageSize);

        Map<String,String> tMparams = new HashMap<>();
        tMparams.put("startDate",startDate);
        tMparams.put("endDate",endDate);
        tMparams.put("tayps",tayps);
        tMparams.put("name",tName);
        tMparams.put("rtxNumber",tRtxNumber);
        //数据装填完毕

        List<ATLeaveExtraDetail> tMapReturn = atLeaveExtraDetailMapper.selectAllByTaypsEx(tMparams);
        if( tMapReturn.size() == 0 ){
            throw new MessageNullValueException("当前条件下无数据！");
        }

        PageInfo<ATLeaveExtraDetail> pageInfo = new PageInfo<>(tMapReturn);

        //转化日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        Map<String,Object> tReturn = new HashMap<>();
        //准备返回数据
        List<ATLeaveExtraVO> allReturnData = new ArrayList<>();
        for (ATLeaveExtraDetail detail : tMapReturn) {
            ATLeaveExtraVO atLeaveExtraVO = new ATLeaveExtraVO();

            atLeaveExtraVO.setRequestNumber(detail.getRequestNumber());
            atLeaveExtraVO.setSectionMID(detail.getSectionMID());
            atLeaveExtraVO.setName(detail.getName());
            atLeaveExtraVO.setRtxNumber(detail.getRtxNumber());
            atLeaveExtraVO.setManufacturers(detail.getManufacturers());
            atLeaveExtraVO.setPost(detail.getPost());
            atLeaveExtraVO.setJobRank(detail.getJobRank());
            atLeaveExtraVO.setServiceOffices(detail.getServiceOffices());
            atLeaveExtraVO.setProjectManager(detail.getProjectManager());
            atLeaveExtraVO.setApplicationType(detail.getApplicationType());
            atLeaveExtraVO.setStartTime(detail.getStartTime());
            atLeaveExtraVO.setLeaveStartType(detail.getLeaveStartType());
            atLeaveExtraVO.setCompletionTime(detail.getCompletionTime());
            atLeaveExtraVO.setDeadlineType(detail.getDeadlineType());
            atLeaveExtraVO.setMemo(detail.getMemo());
            atLeaveExtraVO.setApplicant(detail.getApplicant());
            atLeaveExtraVO.setApplicationDetail(detail.getApplicationDetail());


            //日期StartDay
            if (detail.getStartDay() != null && !"".equals(detail.getStartDay())){
                atLeaveExtraVO.setStartDay(dateFormat.format(detail.getStartDay()));
            }else {
                atLeaveExtraVO.setStartDay("");
            }
            //DeadlineDay
            if (detail.getDeadlineDay() != null && !"".equals(detail.getDeadlineDay())){
                atLeaveExtraVO.setDeadlineDay(dateFormat.format(detail.getDeadlineDay()));
            }else {
                atLeaveExtraVO.setDeadlineDay("");
            }
            //ApplicationTime
            if (detail.getApplicationTime() != null && !"".equals(detail.getApplicationTime())){
                atLeaveExtraVO.setApplicationTime(dateFormat.format(detail.getApplicationTime()));
            }else {
                atLeaveExtraVO.setApplicationTime("");
            }
            //CompletedTime
            if (detail.getCompletedTime() != null && !"".equals(detail.getCompletedTime())){
                atLeaveExtraVO.setCompletedTime(dateFormat.format(detail.getCompletedTime()));
            }else {
                atLeaveExtraVO.setCompletedTime("");
            }

            allReturnData.add(atLeaveExtraVO);
        }
        tReturn.put("total",pageInfo.getTotal());
        tReturn.put("overAndLeavaSheet",allReturnData);

        return tReturn;
    }

    /**
     * 获取请假日期排行
     * @param params
     * @return
     * @throws MessageNullValueException
     */
    @Override
    public Map<String, Object> selectRankingOfLeaveDays(Map<String, Object> params) throws MessageNullValueException {
        //取出 currentMonth 与 count
        String currentMonth = null;
        if(isValidDate(params.get("currentMonth"))){
            currentMonth = (String)params.get("currentMonth") ;
        }else{
            throw new MessageNullValueException("日期传入错误！");
        }
        Integer count = null;
        if (isValidPositiveInteger(params.get("count"))){
            count = Integer.valueOf((String)params.get("count"));
        }else{
            throw new MessageNullValueException("数据量传入错误！");
        }
        //获取原始数据
        Map<String,String> liParams = new HashMap<>();
        //只传入月份
        liParams.put("currentMonth",currentMonth);
        List<Map<String,String>> yuanListMap = selectAbnormalAttendance(liParams);

        if (yuanListMap == null || yuanListMap.isEmpty()){
            throw new MessageNullValueException("当前月份无请假数据！");
        }

        //两个数据的列表存在的map
        Map<String,Float> personData= new HashMap<>();

        for (Map<String, String> stringMap : yuanListMap) {
            /**
             * "rtxNumber": "zkr_wangziyi", 唯一标识
             * "time": "0.5",    请假天长
             * "abName": "王梓屹",  名字
             * "day": "2023-10-31" 哪一天的假
             */
            String key = stringMap.get("abName")+":"+stringMap.get("rtxNumber");
            String valueString = stringMap.get("time");
            Float value = Float.valueOf(valueString);
            if (personData.get(key) !=null ){
                value = personData.get(key)+value;
                personData.put(key,value);
            }else{
                personData.put(key,value);
            }
        }
        //拆分personData为两个列表
        //使用java 8 的流处理
        // 拆分并排序

        Map<String, Float> personToData = personData.entrySet().stream()
                .sorted(Map.Entry.comparingByValue())  // 根据值排序
                .collect(Collectors.toMap(
                        Map.Entry::getKey,  // 保持键的顺序不变
                        Map.Entry::getValue,
                        (existing, replacement) -> existing,  // 如果有重复的键，保留原有的值
                        LinkedHashMap::new  // 使用LinkedHashMap保持插入顺序
                ));
        // 提取person和Data列表
        List<String> dataName = new ArrayList<>(personToData.keySet());
        List<Float> data = new ArrayList<>(personToData.values());
        //判空
        if (dataName ==null ||  dataName.isEmpty()){
            throw new MessageNullValueException("当前月份无请假数据！");
        }

        Map<String,Object> leaveDaysSheet =new HashMap<>();
        int endIndex = Math.min(count, dataName.size());

        leaveDaysSheet.put("dataName",dataName.subList(0,endIndex));
        leaveDaysSheet.put("data",data.subList(0,endIndex));


        return leaveDaysSheet;
    }

    /**
     * 获取迟到缺勤排行
     * @param params
     * @return
     * @throws MessageNullValueException
     */
    @Override
    public Map<String, Object> selectRankingOfLateAndAbsent(Map<String, Object> params) throws MessageNullValueException, ParseException {
        //取出 currentMonth 与 count

        String tCurrentMonth = null;
        if(isValidDate(params.get("currentMonth"))){
            tCurrentMonth = (String)params.get("currentMonth") ;
        }else{
            throw new MessageNullValueException("日期传入错误！");
        }
        Integer count = null;
        if (isValidPositiveInteger(params.get("count"))){
            count = Integer.valueOf((String)params.get("count"));
        }else{
            throw new MessageNullValueException("数据量传入错误！");
        }
        //数据获取
        //两个数据的列表存在的map
        Map<String,Integer> personData=  getMapOfLateAbsent(tCurrentMonth);


        //拆分personData为两个列表
        //使用java 8 的流处理
        // 拆分并排序

        Map<String, Integer> personToData = personData.entrySet().stream()
                .sorted(Map.Entry.comparingByValue())  // 根据值排序
                .collect(Collectors.toMap(
                        Map.Entry::getKey,  // 保持键的顺序不变
                        Map.Entry::getValue,
                        (existing, replacement) -> existing,  // 如果有重复的键，保留原有的值
                        LinkedHashMap::new  // 使用LinkedHashMap保持插入顺序
                ));

        // 提取person和Data列表
        List<String> dataName = new ArrayList<>(personToData.keySet());
        List<Integer> data = new ArrayList<>(personToData.values());

        //判空
        if ( dataName == null || dataName.isEmpty()){
            throw new MessageNullValueException("当前月份无请假数据！");
        }

        Map<String,Object> lateEarlSheet =new HashMap<>();
        int endIndex = Math.min(count, dataName.size());

        lateEarlSheet.put("dataName",dataName.subList(0,endIndex));
        lateEarlSheet.put("data",data.subList(0,endIndex));

        return lateEarlSheet;

    }

    //通过扫每日考勤状况的计算数据，获取迟到缺勤排行
    private Map<String,Integer> getMapOfLateAbsent(String tCurrentMonth) throws MessageNullValueException, ParseException {

        //获取这段时间内的rtx列表
        List<String> rtxList = atDayDetailMapper.selRtxByNameDateRtx(tCurrentMonth, "", "");

        if (rtxList == null || rtxList.isEmpty()) {
            throw new MessageNullValueException("此月暂时无数据！");
        }
        //返回的数据Map
        Map<String,Integer> personData = new HashMap<>();

        //下面开始处理数据
        String yearMonth = tCurrentMonth.substring(0, 7).replace("-", "");

        //每次循环出一个人的数据
        //无返回数据集合的时候需要跳过
        for (int oneRtx = 0 ; oneRtx < rtxList.size(); oneRtx++ ) {
            //s为rtx账号
            String s = rtxList.get(oneRtx);
            Map<String,String> tRtxAll = atteResultsService.buildDetailResult(yearMonth, s);
            //如果无返回数据集，则跳过本次循环
            if(tRtxAll == null || tRtxAll.isEmpty()){
                continue;
            }

            //对一个人一个月的每日数据进行循环。
            String name = tRtxAll.get("name");
            tRtxAll.remove("name");
            String key = name +":"+ s ;
            //每人每天的数据循环
            int times = 1;
            for (int i = 1; i <= 32; i++) {

                //非null，非“”，非“√”
                String date = ""+i;
                if (tRtxAll.get(date) != null&& !"".equals(tRtxAll.get(date)) && !"√".equals(tRtxAll.get(date))){

                    //按日期与rtxNumber单独开一次查询
                    if (tRtxAll.get(date).contains("假")){
                        //假期不记录
                    }else {
                        //其他情况记录
                        personData.put(key,times++);
                    }
                }
            }
        }

        return personData;
    }




    //判断count数据是否为非0 非null 非空的数据
    public  boolean isValidPositiveInteger(Object obj) {
        if (obj == null) {
            return false;
        }
        if ("".equals((String)obj)){
            return false;
        }
        Integer value = Integer.valueOf((String)obj) ;
        return value > 0;
    }

    //判断Object格式的数据非空，非null，且必须为“2023-01-01”格式的字符串数据
    public  boolean isValidDate(Object date) {
        if (date == null) {
            return false;
        }
        try {
            String dateString = date.toString();
            if ( dateString == null || dateString.isEmpty()) {
                return false;
            }
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate.parse(dateString, formatter);
            return true;
        } catch (Exception e) {
            return false;
        }
    }


}
